package net.imagine.backend.mockrmi.remote;

import net.imagine.backend.mockrmi.ServiceBinder;
import net.imagine.backend.mockrmi.ServiceRegistry;
import net.imagine.backend.mockrmi.remote.server.Server;
import net.imagine.backend.mockrmi.remote.server.ServerFactory;
import net.imagine.backend.mockrmi.util.MockRmiUtils;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * ServiceBinder的远程实现类，通过TCP/IP调用
 * 
 * @author wuqh
 * @see ServiceBinder
 */
public class RemoteServiceBinder implements ServiceBinder {
	protected static final Log logger = LogFactory.getLog(RemoteServiceBinder.class);
	protected ServerFactory serverFactory;

	/**
	 * 设置serverFactory对象
	 * 
	 * @param serverFactory
	 */
	public synchronized void setServerFactory(ServerFactory serverFactory) {
		this.serverFactory = serverFactory;
	}

	/**
	 * {@inheritDoc} 其中id的定义为${prort}:${id}
	 */
	@Override
	public void bind(int port, String id, Object target) {
		String realId = MockRmiUtils.genId(port, id);
		if (ServiceRegistry.lookup(realId) != null) {
			logger.warn("can not bind as the service has exist at the server");
		} else {
			rebind(port, id, target);
		}
	}

	/**
	 * {@inheritDoc} 其中id的定义为${prort}:${id}
	 */
	@Override
	public void rebind(int port, String id, Object target) {
		forceBind(port, id, target);
	}

	/**
	 * {@inheritDoc} 其中id的定义为${prort}:${id}
	 */
	@Override
	public void unbind(int port, String id) {
		unbindWithServerShutdownTest(port, id);
	}

	/**
	 * 解绑时检测是否需要关闭服务器(如果服务器没有注册的服务组件)，如果需要则关闭服务器
	 * 
	 * @param port
	 *            服务器端口号
	 * @param id
	 *            注册的服务对象id
	 */
	private synchronized void unbindWithServerShutdownTest(int port, String id) {
		String realId = MockRmiUtils.genId(port, id);
		ServiceRegistry.unbind(realId);
		Server server = serverFactory.getServer(port);
		server.decreaseServiceCount();
		if (server.getServiceCount() == 0) {
			server.shutdown();
		}
	}

	/**
	 * 强制绑定（同重绑规则），如果服务器没有启动则启动服务器
	 * 
	 * @param port
	 *            服务器端口号
	 * @param id
	 *            注册的服务对象id，id必须在当前JVM中唯一
	 * @param target
	 *            注册的服务对象
	 */
	private synchronized void forceBind(int port, String id, Object target) {
		String realId = MockRmiUtils.genId(port, id);
		Server server = serverFactory.getServer(port);
		if (!server.isStartuped()) {
			server.startup();
		}
		ServiceRegistry.regist(realId, target);
		server.increaseServiceCount();
	}

	public static void main(String... args) {
		RemoteServiceBinder binder = new RemoteServiceBinder();
		binder.bind(12345, "123", "12345");
	}
}
